
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include "OsSem.h"
//#include "pub_st.h"
#include "dbgprint.h"
#include "basic_datatype.h"

mp_Os_Mutex_t Os_MutexInit(void)
{
	pthread_mutexattr_t attr; 
	pthread_mutex_t *theMutex = malloc(sizeof( pthread_mutex_t)); 

	pthread_mutexattr_init(&attr); 
	pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP); 
	pthread_mutex_init(theMutex,&attr);
	return (int)theMutex;
}
int Os_MutexDestroy(mp_Os_Mutex_t sid)
{
	return 0;
}

int Os_MutexDelete(mp_Os_Mutex_t sid)
{
	int ret = 0;
	ret = pthread_mutex_destroy((pthread_mutex_t *)sid);
	free((pthread_mutex_t *)sid);
	return ret;
}
int Os_MutexLock(mp_Os_Mutex_t sid)
{
	pthread_mutex_lock((pthread_mutex_t *)sid);
	return 0;
}
int Os_MutexUnlock(mp_Os_Mutex_t sid)
{
	pthread_mutex_unlock((pthread_mutex_t *)sid);
	return 0;
}
int Os_MutexTrylock (int mid)
{
	return 0;
}
int Os_MutexTimedlock (int mid, int millisecond)
{
	return 0;
}

typedef struct tagOsSem
{
    unsigned int    used;
    sem_t   *sem;
}OsSem;
#define MAX_SEM_NUM				(64)
static OsSem hOsSem[MAX_SEM_NUM];

void OS_SemDataInit(void)
{
	memset(&hOsSem,0,MAX_SEM_NUM*sizeof(OsSem));
}

unsigned int Os_SemInit(unsigned int initialTokenCount)
{
    int index;
    sem_t *sem = malloc(sizeof(sem_t));
    
    if (sem_init(sem, 0, initialTokenCount) != 0) 
    {
          LOGD("[ipanel_porting_sem_create]sem_init failed, initialTokenCount=%d \n ",initialTokenCount);
          return 0;
    }
    for (index=0; index<MAX_SEM_NUM;index++) 
    {
        if (hOsSem[index].used == 0) 
        {
            hOsSem[index].used = 1;
            hOsSem[index].sem = sem;
            return (unsigned int)&hOsSem[index];
        }
    }

    LOGD("@@@@@@@@@@@@@[ipanel_porting_sem_create] failed, sem create too much \n");
    return 0;
}

int Os_SemDestroy (unsigned int sem_handle)
{
    OsSem *pSem = (OsSem*)sem_handle;

	//return false;
    if (pSem) {
        if (sem_destroy(pSem->sem) == 0) {
            pSem->used = 0;
            free(pSem->sem);
            pSem->sem = NULL;
            return TRUE;
        }
    }

    LOGD("@@@@@@@@@@@@@[gt_porting_sem_destroy] failed, sem_handle=0x%x \n",sem_handle);
    return FALSE;
}

int Os_SemPost(unsigned int sem_handle)
{
    OsSem *pSem = (OsSem*)sem_handle;

    //return false;
    if (pSem) {
        if (sem_post(pSem->sem)==0) {
            return TRUE;
        }
    }
    LOGD("@@@@@@@@@@@@[gtl_porting_sem_release] failed \n");
    return FALSE;
}


int Os_SemWait(unsigned int sem_handle, unsigned int milliSecsToWait)
{
    OsSem *pSem = (OsSem*)sem_handle;
    int ret;
	//return false;
    if (pSem==NULL) {
        LOGD("[gt_porting_sem_wait] failed ,sem_handle==NULL \n");
        return FALSE;
    }
    
    if (0==milliSecsToWait) {
        if (sem_trywait(pSem->sem) == 0)
            return TRUE;
    }
    else if (-1==milliSecsToWait) {
        if (sem_wait(pSem->sem) == 0)
            return TRUE;
    }
    else if (milliSecsToWait>0) {
        struct timeval temptime;
		struct timespec spec_time;
        gettimeofday(&temptime, NULL);
        temptime.tv_sec += (milliSecsToWait/1000);
        temptime.tv_usec += (milliSecsToWait%1000)*1000;
		spec_time.tv_sec = temptime.tv_sec;
		spec_time.tv_nsec = temptime.tv_usec*1000;
        if ((ret = sem_timedwait(pSem->sem, &spec_time)) == 0) 
            return TRUE;
        else
            LOGD("sem_timedwait ret=%d",ret);
    }
     LOGD("@@@@@@@@@@@@[Os_SemWait] [0x%x]failed \n",sem_handle);
    return FALSE;
}
int Os_SemTrywait(mp_Os_Sem_t sid)
{
	return 0;

}
int Os_SemTimedwait(mp_Os_Sem_t sid, int millisecond)
{
	return 0;

}
